Skip to content

Fix #10: accept OIDC JWTs on /v1/* via inbound chain#11

Merged
cjimti merged 1 commit into
mainfrom
fix-oidc-inbound-chain
May 13, 2026
Merged

Fix #10: accept OIDC JWTs on /v1/* via inbound chain#11
cjimti merged 1 commit into
mainfrom
fix-oidc-inbound-chain

Conversation

@cjimti
Copy link
Copy Markdown
Contributor

@cjimti cjimti commented May 13, 2026

Summary

  • Adds OIDCBearerAuthenticator in pkg/auth/inbound that wraps auth.OIDCAuthenticator with chain-safe semantics (ErrNoCredential for missing or non-JWT bearers, ErrInvalidCredential only when a structurally-valid JWT fails verification).
  • Wires the adapter into the inbound chain as apikey → oidc → bearer, so Authorization: Bearer <jwt> from the configured IdP authenticates on /v1/*.
  • Lifts OIDC validator construction out of buildPortal so the chain and BrowserAuth share one instance — discovery + JWKS fetch run once at startup.

Fixes #10.

Test plan

  • make verify passes locally (gofmt, tidy, build, golangci-lint, gosec, codeql, govulncheck, UI typecheck + build, embedded-SPA sync gate, full Go tests).
  • New table-driven test TestChain_OIDCBeforeBearer covers the four cases from the ticket:
    • Valid JWT with correct issuer/audience → Identity from OIDC.
    • JWT signed by a foreign issuer → ErrInvalidCredential, no fallthrough to static bearer.
    • Static dev token → Identity from BearerAuthenticator (OIDC returns ErrNoCredential on non-JWT).
    • No credential with allow_anonymous=falseErrNoCredential.
  • Adapter unit tests cover looksLikeJWT edges and the nil-validator guard.
  • Smoke against a real Keycloak deployment: curl -H "Authorization: Bearer <jwt>" /v1/whoami returns 200 with subject from the JWT sub claim.

Notes

The ticket's optional proposal #3 (softening BearerAuthenticator to return ErrNoCredential on non-match) was intentionally skipped — it would change behavior for non-OIDC deployments and is not needed here. The OIDC adapter returning ErrNoCredential on non-JWT bearers is enough to preserve the static-dev-token fallthrough.

The inbound chain previously held only api-key + static-bearer
authenticators, so an Authorization: Bearer <jwt> hitting /v1/* was
rejected with 401 even when oidc.enabled was true and the JWT carried
the right issuer/audience — the OIDC validator was wired only into the
portal session flow. Adds an OIDCBearerAuthenticator adapter that
returns ErrNoCredential on non-JWT bearers (so static dev tokens still
fall through) and ErrInvalidCredential only on JWTs that fail
verification; the server now builds one OIDC validator at startup and
shares it between the chain and BrowserAuth. Fixes #10.
@cjimti cjimti merged commit c770ca0 into main May 13, 2026
7 checks passed
@cjimti cjimti deleted the fix-oidc-inbound-chain branch May 13, 2026 17:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

inbound auth chain rejects OIDC JWTs: OIDCAuthenticator is built but never added to the chain

1 participant